package dk.degofedal.scala.math.numerical

class NewtonRaphson {

	type T = Double
	val diff = 1e-8
	
	def solve[Double](x: T, f: ((T) => T) ) : (T, Int) = {
	
		val delta = 1e-5
		
		def solveInner(x: T, i: Int)(f: (T) => T) : (T, Int) = {
			val f_x = f(x)
			val f_dx = f(x+delta)
			
			if(Math.abs(f_x) < diff) {
				(x, i)
			} else {
				val r = x - (f_x / ((f_dx-f_x)/delta))
				solveInner(r, i+1)(f)
			}
		}
	
		solveInner(x, 0)(f)
	}
	
	def solve[Double](x: T, f: ((T) => T), df: ((T) => T) ) : (T, Int) = {
		
		def solveInner(x: T, i: Int)(f: (T) => T)(df: (T) => T) : (T, Int) = {
			val f_x = f(x)
			
			if(Math.abs(f_x) < diff) {
				(x, i)
			} else {
				val r = x - (f_x / df(x))
				solveInner(r, i+1)(f)(df)
			}
		}
		
		solveInner(x, 0)(f)(df)
	}
}